package com.epfly.base.hv;

import com.epfly.base.ex.PromoException;
import com.epfly.base.ex.PromoMessageEnum;
import com.epfly.base.vo.BaseResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

@Slf4j
@RestControllerAdvice
public class ValidationHandlers {

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<BaseResp> errorHandler(Exception exception) {

        if (exception instanceof PromoException) {
            PromoException promoException = (PromoException)exception;
            ResponseEntity<BaseResp> responseEntity = ResponseEntity
                    .ok()
                    .body(BaseResp.baseRespBuilder().errCode(promoException.getErrCode()).errMsg(promoException.getErrMsg())
                            .build());
            return responseEntity;
        }
        String message = exception.getMessage();
        log.error("unexpected>", exception);
        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40004.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }

    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public ResponseEntity<BaseResp> errorHandler(HttpMessageNotReadableException exception) {

        String message = exception.getMessage();

        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40003.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }


    /**
     *  hibernate-validator注解校验
     * {@link javax.validation.constraints.NotNull}
     * {@link javax.validation.constraints.NotEmpty}
     * ......
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity<BaseResp> errorHandler(ConstraintViolationException exception) {
        for (ConstraintViolation<?> constraintViolation : exception.getConstraintViolations()) {
            String qualifiedName = constraintViolation.getRootBeanClass() + "#" +constraintViolation.getPropertyPath().toString();
            String message = constraintViolation.getMessage();
            log.warn("qualifiedName={}, msg={}", qualifiedName, message);
        }
        String message = exception.getConstraintViolations().iterator().next().getMessage();

        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40001.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }

    /**
     * {@link org.springframework.web.bind.annotation.RequestParam} 注解校验
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResponseEntity<BaseResp> errorHandler(MissingServletRequestParameterException exception) {
        String message = exception.getMessage();
        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40000.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }

    /**
     * 表单请求校验结果处理
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseEntity<BaseResp> errorHandler(BindException bindException) {
        BindingResult bindingResult = bindException.getBindingResult();
        String message = bindingResult.getAllErrors().iterator().next().getDefaultMessage();

        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40002.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }

    /**
     * JSON请求校验结果，也就是请求中对实体标记了@RequestBody
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<BaseResp> errorHandler(MethodArgumentNotValidException methodArgumentNotValidException) {


        ObjectError next = methodArgumentNotValidException.getBindingResult().getAllErrors().iterator().next();
        String message = next.getDefaultMessage();
        ConstraintViolation constraintViolation = next.unwrap(ConstraintViolation.class);
        String qualifiedName = constraintViolation.getRootBeanClass() + "#" +constraintViolation.getPropertyPath().toString();

        log.warn("qualifiedName={}, msg={}", qualifiedName, message);
        ResponseEntity<BaseResp> responseEntity = ResponseEntity
                .ok()
                .body(BaseResp.baseRespBuilder().errCode(PromoMessageEnum.ERR_40002.getErrCode()).errMsg(message)
                        .build());
        return responseEntity;
    }

}